package cn.com.dcsgo.ioc.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 通过配置类配置: 要扫描注解的包、配置文件
 *
 * @author Dcsgo
 * @since 2025/2/5 12:31
 */
@Configuration //标识是一个配置类
@ComponentScan("cn.com.dcsgo.ioc.simple") //扫描的包，可以通过数组的形式传入多个，不需要包含配置文件本身
@PropertySource("classpath:jdbc.properties") //配置文件的配置
public class JavaConfiguration {
    /**
     * 外部配置信息还是通过@Value注解获取
     */
    @Value("${mysql.version}")
    private String mysqlVersion;

    /**
     * 注解 @Value 还可以用于形参列表用于读取配置并传参给相应的参数
     * 注解 @Bean 用在方法上表示该方法是对bean的配置，作用同xml配置文件中的bean标签
     * bean的id就是方法名，class就是返回类型(也可以是实际返回对象的父类或接口)
     * bean的id还可以通过@Bean注解的value属性或者name属性指定
     * 周期方法可以通过 initMethod 和 destroyMethod 属性指定
     * 作用域可以通过@Scope注解配置
     *
     * @param url      url
     * @param driver   driver
     * @param username username
     * @param password password
     * @return DruidDataSource
     */
    @Bean(initMethod = "init", destroyMethod = "close")
    @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
    public DruidDataSource druidDataSource(
            @Value("${mysql.url}") String url,
            @Value("${mysql.driver}") String driver,
            @Value("${mysql.username}") String username,
            @Value("${mysql.password}") String password) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driver);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Value("${mysql.url}")
    private String url;
    @Value("${mysql.driver}")
    private String driver;
    @Value("${mysql.username}")
    private String username;
    @Value("${mysql.password}")
    private String password;

    @Bean
    public DruidDataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driver);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    /**
     * 通过@Bean方法配置的bean如何被其他@Bean方法引用呢？
     * 直接调用需要的bean的@Bean方法或者用形参变量引入
     *
     * @return JdbcTemplate
     */
    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource());
    }

    /**
     * 如果有多个与形参匹配的bean则需要bean id = 形参名
     * @param dataSource dataSource
     * @return JdbcTemplate
     */
    @Bean
    public JdbcTemplate jdbcTemplate1(DruidDataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}
